home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / sectools / fragrouter / libpcap-0.4 / pcap-linux.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-26  |  7.3 KB  |  332 lines

  1. /*
  2.  * Copyright (c) 1996, 1997
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21. #ifndef lint
  22. static const char rcsid[] =
  23.     "@(#) $Header: /cvs/fragrouter/libpcap-0.4/pcap-linux.c,v 1.1.1.1 1999/05/03 04:06:44 dugsong Exp $ (LBL)";
  24. #endif
  25.  
  26. #include <sys/param.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/socket.h>
  29. #include <sys/time.h>
  30.  
  31. #include <net/if.h>
  32. #ifdef HAVE_NET_IF_ARP_H
  33. #include <net/if_arp.h>
  34. #else
  35. #include <linux/if_arp.h>
  36. #endif
  37. #include <linux/if_ether.h>
  38.  
  39. #include <netinet/in.h>
  40.  
  41. #include <errno.h>
  42. #include <malloc.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <unistd.h>
  47.  
  48. static struct ifreq saved_ifr;
  49.  
  50. #include "pcap-int.h"
  51.  
  52. #include "gnuc.h"
  53. #ifdef HAVE_OS_PROTO_H
  54. #include "os-proto.h"
  55. #endif
  56.  
  57. void linux_restore_ifr(void);
  58.  
  59. int
  60. pcap_stats(pcap_t *p, struct pcap_stat *ps)
  61. {
  62.  
  63.     *ps = p->md.stat;
  64.     return (0);
  65. }
  66.  
  67. int
  68. pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
  69. {
  70.     register int cc;
  71.     register int bufsize;
  72.     register int caplen;
  73.     register u_char *bp;
  74.     struct sockaddr from;
  75.     int fromlen;
  76.  
  77.     bp = p->buffer + p->offset;
  78.     bufsize = p->bufsize;
  79.     if (p->md.pad > 0) {
  80.         memset(bp, 0, p->md.pad);
  81.         bp += p->md.pad;
  82.         bufsize -= p->md.pad;
  83.     }
  84.  
  85. again:
  86.     do {
  87.         fromlen = sizeof(from);
  88.         cc = recvfrom(p->fd, bp, bufsize, 0, &from, &fromlen);
  89.         if (cc < 0) {
  90.             /* Don't choke when we get ptraced */
  91.             switch (errno) {
  92.  
  93.             case EINTR:
  94.                     goto again;
  95.  
  96.             case EWOULDBLOCK:
  97.                 return (0);        /* XXX */
  98.             }
  99.             sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
  100.             return (-1);
  101.         }
  102.     } while (strcmp(p->md.device, from.sa_data));
  103.  
  104.     /* If we need have leading zero bytes, adjust count */
  105.     cc += p->md.pad;
  106.     bp = p->buffer + p->offset;
  107.  
  108.     /* If we need to step over leading junk, adjust count and pointer */
  109.     cc -= p->md.skip;
  110.     bp += p->md.skip;
  111.  
  112.     /* Captured length can't exceed our read buffer size */
  113.     caplen = cc;
  114.     if (caplen > bufsize)
  115.         caplen = bufsize;
  116.  
  117.     /* Captured length can't exceed the snapshot length */
  118.     if (caplen > p->snapshot)
  119.         caplen = p->snapshot;
  120.  
  121.     if (p->fcode.bf_insns == NULL ||
  122.         bpf_filter(p->fcode.bf_insns, bp, cc, caplen)) {
  123.         struct pcap_pkthdr h;
  124.  
  125.         ++p->md.stat.ps_recv;
  126.         /* Get timestamp */
  127.         if (ioctl(p->fd, SIOCGSTAMP, &h.ts) < 0) {
  128.             sprintf(p->errbuf, "SIOCGSTAMP: %s",
  129.                 pcap_strerror(errno));
  130.             return (-1);
  131.         }
  132.         h.len = cc;
  133.         h.caplen = caplen;
  134.         (*callback)(user, &h, bp);
  135.         return (1);
  136.     }
  137.     return (0);
  138. }
  139.  
  140. pcap_t *
  141. pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
  142. {
  143.     register int fd, broadcast;
  144.     register pcap_t *p;
  145.     struct ifreq ifr;
  146.     struct sockaddr sa;
  147.  
  148.     p = (pcap_t *)malloc(sizeof(*p));
  149.     if (p == NULL) {
  150.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  151.         return (NULL);
  152.     }
  153.     memset(p, 0, sizeof(*p));
  154.     fd = -1;
  155.  
  156.     fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
  157.     if (fd < 0) {
  158.         sprintf(ebuf, "socket: %s", pcap_strerror(errno));
  159.         goto bad;
  160.     }
  161.     p->fd = fd;
  162.  
  163.     /* Bind to the interface name */
  164.     memset(&sa, 0, sizeof(sa));
  165.     sa.sa_family = AF_INET;
  166.     (void)strncpy(sa.sa_data, device, sizeof(sa.sa_data));
  167.     if (bind(p->fd, &sa, sizeof(sa))) {
  168.         sprintf(ebuf, "bind: %s: %s", device, pcap_strerror(errno));
  169.         goto bad;
  170.     }
  171.  
  172.     memset(&ifr, 0, sizeof(ifr));
  173.     strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  174.     if (ioctl(p->fd, SIOCGIFHWADDR, &ifr) < 0 ) {
  175.         sprintf(ebuf, "SIOCGIFHWADDR: %s", pcap_strerror(errno));
  176.         goto bad;
  177.     }
  178.     broadcast = 0;
  179.     switch (ifr.ifr_hwaddr.sa_family) {
  180.  
  181.     case ARPHRD_ETHER:
  182.     case ARPHRD_METRICOM:
  183.         p->linktype = DLT_EN10MB;
  184.         p->offset = 2;
  185.         ++broadcast;
  186.         break;
  187.  
  188.     case ARPHRD_EETHER:
  189.         p->linktype = DLT_EN3MB;
  190.         ++broadcast;
  191.         break;
  192.  
  193.     case ARPHRD_AX25:
  194.         p->linktype = DLT_AX25;
  195.         ++broadcast;
  196.         break;
  197.  
  198.     case ARPHRD_PRONET:
  199.         p->linktype = DLT_PRONET;
  200.         break;
  201.  
  202.     case ARPHRD_CHAOS:
  203.         p->linktype = DLT_CHAOS;
  204.         break;
  205.  
  206.     case ARPHRD_IEEE802:
  207.         p->linktype = DLT_IEEE802;
  208.         ++broadcast;
  209.         break;
  210.  
  211.     case ARPHRD_ARCNET:
  212.         p->linktype = DLT_ARCNET;
  213.         ++broadcast;
  214.         break;
  215.  
  216.     case ARPHRD_SLIP:
  217.     case ARPHRD_CSLIP:
  218.     case ARPHRD_SLIP6:
  219.     case ARPHRD_CSLIP6:
  220.     case ARPHRD_PPP:
  221.         p->linktype = DLT_RAW;
  222.         break;
  223.  
  224.     case ARPHRD_LOOPBACK:
  225.         p->linktype = DLT_NULL;
  226.         p->md.pad = 2;
  227.         p->md.skip = 12;
  228.         break;
  229.  
  230. #ifdef ARPHRD_FDDI
  231.     /* Not all versions of the kernel has this define */
  232.     case ARPHRD_FDDI:
  233.         p->linktype = DLT_FDDI;
  234.         ++broadcast;
  235.         break;
  236. #endif
  237.  
  238. #ifdef notdef
  239.     case ARPHRD_LOCALTLK:
  240.     case ARPHRD_NETROM:
  241.     case ARPHRD_APPLETLK:
  242.     case ARPHRD_DLCI:
  243.     case ARPHRD_RSRVD:
  244.     case ARPHRD_ADAPT:
  245.     case ARPHRD_TUNNEL:
  246.     case ARPHRD_TUNNEL6:
  247.     case ARPHRD_FRAD:
  248.     case ARPHRD_SKIP:
  249.         /* XXX currently do not know what to do with these... */
  250.         abort();
  251. #endif
  252.  
  253.     default:
  254.         sprintf(ebuf, "unknown physical layer type 0x%x",
  255.             ifr.ifr_hwaddr.sa_family);
  256.         goto bad;
  257.     }
  258.  
  259.     /* Base the buffer size on the interface MTU */
  260.     memset(&ifr, 0, sizeof(ifr));
  261.     strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
  262.     if (ioctl(p->fd, SIOCGIFMTU, &ifr) < 0 ) {
  263.         sprintf(ebuf, "SIOCGIFMTU: %s", pcap_strerror(errno));
  264.         goto bad;
  265.     }
  266.  
  267.     /* Leave room for link header (which is never large under linux...) */
  268.     p->bufsize = ifr.ifr_mtu + 64;
  269.  
  270.     p->buffer = (u_char *)malloc(p->bufsize + p->offset);
  271.     if (p->buffer == NULL) {
  272.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  273.         goto bad;
  274.     }
  275.  
  276.     /* XXX */
  277.     if (promisc && broadcast) {
  278.         memset(&ifr, 0, sizeof(ifr));
  279.         strcpy(ifr.ifr_name, device);
  280.         if (ioctl(p->fd, SIOCGIFFLAGS, &ifr) < 0 ) {
  281.             sprintf(ebuf, "SIOCGIFFLAGS: %s", pcap_strerror(errno));
  282.             goto bad;
  283.         }
  284.         saved_ifr = ifr;
  285.         ifr.ifr_flags |= IFF_PROMISC;
  286.         if (ioctl(p->fd, SIOCSIFFLAGS, &ifr) < 0 ) {
  287.             sprintf(ebuf, "SIOCSIFFLAGS: %s", pcap_strerror(errno));
  288.             goto bad;
  289.         }
  290.         ifr.ifr_flags &= ~IFF_PROMISC;
  291.         atexit(linux_restore_ifr);
  292.     }
  293.  
  294.     p->md.device = strdup(device);
  295.     if (p->md.device == NULL) {
  296.         sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
  297.         goto bad;
  298.     }
  299.     p->snapshot = snaplen;
  300.  
  301.     return (p);
  302. bad:
  303.     if (fd >= 0)
  304.         (void)close(fd);
  305.     if (p->buffer != NULL)
  306.         free(p->buffer);
  307.     if (p->md.device != NULL)
  308.         free(p->md.device);
  309.     free(p);
  310.     return (NULL);
  311. }
  312.  
  313. int
  314. pcap_setfilter(pcap_t *p, struct bpf_program *fp)
  315. {
  316.  
  317.     p->fcode = *fp;
  318.     return (0);
  319. }
  320.  
  321. void
  322. linux_restore_ifr(void)
  323. {
  324.     register int fd;
  325.  
  326.     fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
  327.     if (fd < 0)
  328.         fprintf(stderr, "linux socket: %s", pcap_strerror(errno));
  329.     else if (ioctl(fd, SIOCSIFFLAGS, &saved_ifr) < 0)
  330.         fprintf(stderr, "linux SIOCSIFFLAGS: %s", pcap_strerror(errno));
  331. }
  332.